package com.zjw.remotecall.streamacceptor;

import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;


/**
 * AIDL生成ByteBinder，只在Proxy增加{@link StreamAcceptor.IStream} 接口
 *
 * @author zhong.jw
 */
public interface IByteBinder extends android.os.IInterface {

    String TAG = "IByteBinder";

    /**
     * Default implementation for IByteBinder.
     */
    class Default implements IByteBinder {
        @Override
        public byte[] waitBytes(String key) throws RemoteException {
            return null;
        }

        @Override
        public IBinder asBinder() {
            return null;
        }
    }

    /**
     * Local-side IPC implementation stub class.
     */
    abstract class Stub extends android.os.Binder implements IByteBinder {
        /**
         * INaviBinder.DESCRIPTOR
         */
        private final String mDescriptor;

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub(String descriptor) {
            mDescriptor = descriptor;
            this.attachInterface(this, mDescriptor);
        }

        /**
         * Cast an IBinder object into an IByteBinder interface,
         * generating a proxy if needed.
         */
        public static IByteBinder asInterface(IBinder obj, String descriptor) {
            if ((obj == null)) {
                return null;
            }
            if (descriptor == null) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(descriptor);
            if ((iin instanceof IByteBinder)) {
                return ((IByteBinder) iin);
            }
            return new Proxy(obj, descriptor);
        }

        @Override
        public IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws RemoteException {
            String descriptor = mDescriptor;
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
                case TRANSACTION_waitBytes: {
                    data.enforceInterface(descriptor);
                    String _arg0;
                    _arg0 = data.readString();
                    byte[] _result = this.waitBytes(_arg0);
                    reply.writeNoException();
                    reply.writeByteArray(_result);
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }

        static class Proxy implements IByteBinder, StreamAcceptor.IStream {

            private final IBinder mRemote;

            private final String mDescriptor;

            Proxy(IBinder remote, String descriptor) {
                mRemote = remote;
                mDescriptor = descriptor;
            }

            @Override
            public IBinder asBinder() {
                return mRemote;
            }

            public String getInterfaceDescriptor() {
                return mDescriptor;
            }

            @Override
            public byte[] waitBytes(String key) throws RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                byte[] _result;
                try {
                    _data.writeInterfaceToken(mDescriptor);
                    _data.writeString(key);
                    boolean _status = mRemote.transact(Stub.TRANSACTION_waitBytes, _data, _reply, 0);
                    if (!_status && getDefaultImpl() != null) {
                        return getDefaultImpl().waitBytes(key);
                    }
                    _reply.readException();
                    _result = _reply.createByteArray();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

            public static IByteBinder sDefaultImpl;

            @Override
            public byte[] waitForBytes(String key) {
                try {
                    return waitBytes(key);
                } catch (RemoteException e) {
                    Log.e("waitForBytes :", e.getMessage() == null ? "null-message" : e.getMessage());
                }
                return new byte[]{};
            }
        }

        static final int TRANSACTION_waitBytes = (IBinder.FIRST_CALL_TRANSACTION);

        public static boolean setDefaultImpl(IByteBinder impl) {
            // Only one user of this interface can use this function
            // at a time. This is a heuristic to detect if two different
            // users in the same process use this function.
            if (Proxy.sDefaultImpl != null) {
                throw new IllegalStateException("setDefaultImpl() called twice");
            }
            if (impl != null) {
                Proxy.sDefaultImpl = impl;
                return true;
            }
            return false;
        }

        public static IByteBinder getDefaultImpl() {
            return Proxy.sDefaultImpl;
        }
    }

    byte[] waitBytes(String key) throws RemoteException;
}
